package com.aiddea.maps;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.content.Context;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;

public class GeoWikiInfo {
	
	// Keys / Defaults de substitució
	final static String CS_KEY_LAT  	= "~lat~";
	final static String CS_KEY_LONG 	= "~lng~";
	final static String CS_KEY_LANG 	= "~lang~";
	final static String CS_KEY_USERNAME = "~username~";
	final static String CS_KEY_MAXROWS  = "~~maxRows~";
	final static String CS_KEY_RADIUS	= "~radius~";
	final static String CS_DEF_LANG 	= "es";
	final static String CS_DEF_USERNAME = "wakumaku";
	final static int 	CS_DEF_MAXROWS 	= 10;
	final static Double CS_DEF_RADIUS  	= 1.0; //(en Km)
	// --
	final static String CS_WIKIURL  	= 
	"http://api.geonames.org/findNearbyWikipediaJSON?"+
		"lat="		+ CS_KEY_LAT	 +
		"&lng="		+ CS_KEY_LONG	 +
		"&lang="	+ CS_KEY_LANG	 +
		"&username="+ CS_KEY_USERNAME+
		"&maxRows="	+ CS_KEY_MAXROWS +
		"&radius="	+ CS_KEY_RADIUS	 ;
	
	private int	   Latitud  = 0;	
	private int	   Longitud = 0;
	private String Username = "";
	private String Language = "";
	private Double Radius   = 0.0;
	private int    MaxRows  = 5;
	
	private List<GWI_Element> GWI_Items = new ArrayList<GWI_Element>();

	private Context meContext   = null;
	
	
	/* Constructor
	 * @param gPoint: Punt geo
	 * @param mContext: Context APP
	 * @return Constructor GeoWikiInfo
	 */
	public GeoWikiInfo(GeoPoint gPoint, Context mContext) {
		
		initClass(gPoint.getLatitudeE6(), gPoint.getLongitudeE6(),mContext,CS_DEF_LANG,CS_DEF_USERNAME, CS_DEF_RADIUS, CS_DEF_MAXROWS);
	}
	
	/* Constructor
	 * @param gPoint: Punt geo
	 * @param mContext: Context APP
	 * @param Lang: Idioma
	 * @param User: Usuari
	 * @return Constructor GeoWikiInfo
	 */
	public GeoWikiInfo(GeoPoint gPoint, Context mContext, String Lang, String User) {
		
		initClass(gPoint.getLatitudeE6(), gPoint.getLongitudeE6(), mContext, Lang, User, CS_DEF_RADIUS, CS_DEF_MAXROWS);
		
	}
	
	/* Constructor
	 * @param iLatitud: Latidud
	 * @param iLongitud: Longitud
	 * @param mContext: Context APP
	 * @return Constructor GeoWikiInfo
	 */
	public GeoWikiInfo(int iLatitud, int iLongitud, Context mContext) 
	{
	
		initClass(iLatitud, iLongitud,mContext,CS_DEF_LANG,CS_DEF_USERNAME, CS_DEF_RADIUS, CS_DEF_MAXROWS);
		
	}
	
	/* Constructor
	 * @param iLatitud: Latidud
	 * @param iLongitud: Longitud
	 * @param mContext: Context APP
	 * @param Lang: Idioma
	 * @param User: Usuari
	 * @return Constructor GeoWikiInfo
	 */
	public GeoWikiInfo(int iLatitud, int iLongitud, Context mContext, String Lang, String User) {
		
		initClass(iLatitud, iLongitud, mContext, Lang, User, CS_DEF_RADIUS, CS_DEF_MAXROWS);
		
	}
	
	public GeoWikiInfo(int iLatitud, int iLongitud, Context mContext, String Lang, String User, Double Radius, int MaxRows) {
		
		initClass(iLatitud, iLongitud, mContext, Lang, User, Radius, MaxRows);
		
	}
	
	/*
	 * @description Inicialitza la clase.
	 */
	public void initClass(int iLatitud, int iLongitud,Context mContext, String Lang, String Username, Double Radius, int MaxRows)
	{
		this.meContext = mContext;
		
		setLatitud(iLatitud);
		setLongitud(iLongitud);
		setUsername(Username);
		setLanguage(Lang);
		setRadius(Radius);	
		setMaxRows( MaxRows); // TODO: Crear constructor que accepti un Array de parametres
		
		loadGeoWikiInfo();
		
	}
	
	/*
	 * Construeix la URL final per fer la petició
	 */
	private String getUrlGeoWikiInfo()
	{
		
		String 
		sRes = CS_WIKIURL.replaceAll(CS_KEY_LAT, String.valueOf(getLatitud()));
		sRes = sRes.replaceAll(CS_KEY_LONG, String.valueOf(getLongitud()));
		sRes = sRes.replaceAll(CS_KEY_LANG, getLanguage());
		sRes = sRes.replaceAll(CS_KEY_USERNAME, getUsername());
		sRes = sRes.replaceAll(CS_KEY_MAXROWS, String.valueOf(getMaxRows()));
		sRes = sRes.replaceAll(CS_KEY_RADIUS, String.valueOf(getRadius()));
		
		return sRes;
	}
	
	/*
	 * Carrega les dades
	 */
	private boolean loadGeoWikiInfo()
	{

		String json;
		// json = getHttpData_Test();
		try {
			// Intentem recuperar les dades...
			json = getHttpData(getUrlGeoWikiInfo());
			
		} catch (Exception e1) {
			e1.printStackTrace();
			// Si la conexió falla, retornem el JSON de proves
			json = getHttpData_Test();
		}
			
		JSONObject object;		
		try {
			//
			object = (JSONObject) new JSONTokener(json).nextValue();
			JSONArray locations = null;
						
			if(!object.has("status"))
			{
				if(object.getJSONArray("geonames").length()>0)
				{
					locations = object.getJSONArray("geonames");
				}
			}
			else
			{
				json = getHttpData_Test();
			}
		
			
			// Carreguem la llista de Locations 
			if(locations != null)
			{
				JSONObject eLem = null;
				for (int i = 0; i < locations.length(); i++) {
					eLem = locations.getJSONObject(i);
					// Els 3 primers paràmetres ens els inventem. Al constructor es regeneraràn.
					// Al passar eLem, ja s'encarrega de carregar les dades necessàries.
					getGWI_Items().add(new GWI_Element(null, "0", "0", eLem));	
				}
			}
			
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return true;
	}
	
	private String getHttpData(String sURL) throws Exception
	{
		String reponse = "";
		
		URL wiki = new URL(sURL);
		
        URLConnection wk = wiki.openConnection();
                
        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                wk.getInputStream()));
        
        String inputLine;
        while ((inputLine = in.readLine()) != null)
        {
        	reponse += inputLine;
        }
        
        in.close();
		    
	   return reponse;
	}
	
	private String getHttpData_Test()
	{
		return "{\"geonames\":[{\"summary\":\"El Glärnisch es un macizo situado en los Alpes glaroneses, en Suiza central. El área que ocupa pertenece en su totalidad al cantón de Glaris. La ciudad de Glaris se encuentra al este, justo al pie del macizo. Esta compuesto por dos crestas montañosas ordenadas en forma de V, encerrando estas el (...)\",\"distance\":\"0.1869\",\"rank\":79,\"title\":\"XGlärnisch\",\"wikipediaUrl\":\"es.wikipedia.org/wiki/Gl%C3%A4rnisch\",\"elevation\":2914,\"countryCode\":\"CH\",\"lng\":8.998611,\"feature\":\"mountain\",\"lang\":\"es\",\"lat\":46.998611,\"population\":0},{\"summary\":\"El río Linth (Limmat después de la salida del lago de Zúrich) es un río suizo de 140 km de longitud. Nace en los glaciares del macizo del Tödi, en los Alpes glaroneses, y fluye hacía el norte por el cantón de Glaris (...)\",\"distance\":\"2.0229\",\"rank\":96,\"title\":\"XLinth\",\"wikipediaUrl\":\"es.wikipedia.org/wiki/Linth\",\"elevation\":0,\"lng\":9.0095,\"feature\":\"waterbody\",\"lang\":\"es\",\"lat\":46.983,\"population\":0},{\"summary\":\"Luchsingen es una comuna suiza del cantón de Glaris. Limita al nortoeste con la comuna de Glaris, al norte con Schwanden, al este con Haslen, al sur con Elm, Betschwanden y Braunwald, y al oeste con Muotathal (SZ) (...)\",\"distance\":\"4.6104\",\"rank\":95,\"title\":\"XLuchsingen\",\"wikipediaUrl\":\"es.wikipedia.org/wiki/Luchsingen\",\"elevation\":0,\"countryCode\":\"CH\",\"lng\":9.037219,\"feature\":\"city\",\"lang\":\"es\",\"lat\":46.967219,\"population\":0},{\"summary\":\"Haslen es una comuna suiza del cantón de Glaris. Limita al norte y al este con la comuna de Schwanden, y al sur y al oeste con Luchsingen. La comuna actual incorpora los territorios de las antiguas comunas de Leuggelbach y Nidfurn, las cuales se fusionaron con Haslen el 1 de julio de 2006 (...)\",\"distance\":\"4.6564\",\"rank\":94,\"title\":\"XHaslen\",\"wikipediaUrl\":\"es.wikipedia.org/wiki/Haslen\",\"elevation\":0,\"countryCode\":\"CH\",\"lng\":9.054994,\"feature\":\"city\",\"lang\":\"es\",\"lat\":46.981383,\"population\":0},{\"summary\":\"El cantón de Appenzell Rodas Exteriores (en alemán: Appenzell Ausserrhoden; en francés: Appenzell Rhodes-Extérieures, en italiano: Appenzello Esterno) es un semicantón de Suiza. La sede del gobierno cantonal se encuentra en Herisau, aunque la sede judicial se halla en Trogen (...)\",\"distance\":\"5.7012\",\"rank\":100,\"title\":\"XCantón de Appenzell Rodas Exteriores\",\"wikipediaUrl\":\"es.wikipedia.org/wiki/Cant%C3%B3n_de_Appenzell_Rodas_Exteriores\",\"elevation\":0,\"countryCode\":\"CH\",\"lng\":9.016666666666667,\"feature\":\"adm1st\",\"lang\":\"es\",\"lat\":47.05,\"population\":0}]}";
	}
	
	
	// Bucle de prova per mostrar la info recuperada.
	public void showInfo()
	{
		int i = 1;
		for (GWI_Element GWList : getGWI_Items()) {
			Toast.makeText(meContext, i + " - " + GWList.getTitle() + "\n" + GWList.getLatM(), Toast.LENGTH_SHORT).show();
			i++;
		}
		
	}
	
	private void setLongitud(int longitud) {
		Longitud = longitud;
	}

	public int getLongitud() {
		return Longitud;
	}

	private void setLatitud(int latitud) {
		Latitud = latitud;
	}

	public int getLatitud() {
		return Latitud;
	}

	public void setUsername(String username) {
		this.Username = username;
	}

	public String getUsername() {
		return Username;
	}

	public void setLanguage(String language) {
		Language = language;
	}

	public String getLanguage() {
		return Language;
	}

	public void setRadius(Double radius) {
		Radius = radius;
	}

	public Double getRadius() {
		return Radius;
	}

	public void setMaxRows(int maxRows) {
		MaxRows = maxRows;
	}

	public int getMaxRows() {
		return MaxRows;
	}
		
	public List<GWI_Element> getGWI_Items() {
		return GWI_Items;
	}
	
}
